home *** CD-ROM | disk | FTP | other *** search
- /*
- File: uLawCompressor.c
-
- Contains: uLaw Compression Sound Component
-
- Written by: Jim Reekes
-
- Copyright: © 1991-1998 by Apple Computer, Inc., all rights reserved.
-
- */
- #if defined(_MSC_VER) && !defined(__MWERKS__)
- #pragma warning(disable:4229) // ignore anachronism used: modifiers on data are ignored
- #endif
-
- #include <MacTypes.h>
- #include <Errors.h>
- #include <Endian.h>
- #include <Components.h>
- #include <MacMemory.h>
- #include <Resources.h>
- #include <Controls.h>
- #include <Dialogs.h>
- #include <Sound.h>
- #include <MoviesFormat.h>
-
- #include "uLawCodec.h"
-
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // Constants
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- #define kInputFormat k16BitNativeEndianFormat /* required input format */
- #define kOutputFormat kCodecFormat /* only formats we output */
-
- #define ZEROTRAP 1 /* turn on the trap as per the MIL-STD */
-
- enum {
- kOutputSampleSize = 16, /* size of output samples */
- kOutputSamples = ((kMaxOutputSamples / kULawBlockSamples) * kULawBlockSamples), /* max actual samples in output buffer */
- kOutputBufferBytes = ((kMaxOutputSamples / kULawBlockSamples) * kULawBlockBytes * 2), /* room for ULaw stereo data */
- kLeftoverBufferBytes = (kULawBlockSamples * 2 * 2), /* room for leftover stereo 16-bit samples */
-
- kInputSampleSize = 16,
-
- BIAS = 0x84, /* define the add-in bias for 16 bit samples */
- CLIP = 32635,
-
- kOptionCheckBox = 4
- };
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // types
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- #if PRAGMA_STRUCT_ALIGN
- #pragma options align=mac68k
- #elif PRAGMA_STRUCT_PACKPUSH
- #pragma pack(push, 2)
- #elif PRAGMA_STRUCT_PACK
- #pragma pack(2)
- #endif
-
- // Keep your data long word aligned for best performance
-
- typedef struct {
- ComponentInstance self; /* our instance */
- ComponentInstance sourceComponent; /* who to call for more source data */
- SoundComponentDataPtr sourceDataPtr; /* pointer to source data descriptor */
- SoundComponentData outputData; /* local data descriptor record */
- SoundSource sourceID;
- long outputBufferSamples; /* no. samples in output buffer */
- CompressionInfo sourceCompInfo; /* info about source data format */
- CompressionInfo destCompInfo; /* info about destination data format */
- Handle ulawTableHandle; /* resource handle to ulaw table */
- Byte *ulawTable; /* pointer to ulaw table */
- unsigned long leftOverSamples; /* no. samples in leftover buffer */
- Byte leftOverBuffer[kLeftoverBufferBytes]; /* space for leftover samples */
- Byte buffer[kOutputBufferBytes + kLeftoverBufferBytes]; /* buffer space */
- } ULawCompGlobals, *ULawCompGlobalsPtr;
-
- typedef struct {
- AudioFormatAtom formatData;
- AudioEndianAtom endianData;
- AudioTerminatorAtom terminatorData;
- } AudioCompressionAtom, *AudioCompressionAtomPtr, **AudioCompressionAtomHandle;
-
- #if PRAGMA_STRUCT_ALIGN
- #pragma options align=reset
- #elif PRAGMA_STRUCT_PACKPUSH
- #pragma pack(pop)
- #elif PRAGMA_STRUCT_PACK
- #pragma pack()
- #endif
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // Prototypes
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- static OSErr DisplayOptionsDialog(ULawCompGlobalsPtr globals);
- static void SetButtonState(DialogPtr dialog, short item, Boolean state);
- static short GetButtonState(DialogPtr dialog, short item);
- static OSErr GetCompressionParams(ULawCompGlobalsPtr globals, AudioCompressionAtomHandle *params);
- static OSErr SetCompressionParams(ULawCompGlobalsPtr globals, UserDataAtom *atom);
- static ComponentResult PrimeSource(ULawCompGlobalsPtr globals);
- static unsigned long SamplesToBytes(unsigned long sampleCount, CompressionInfoPtr compInfo);
- static unsigned long BytesToSamples(unsigned long byteCount, CompressionInfoPtr compInfo);
- static unsigned long SamplesToFrames(unsigned long sampleCount, CompressionInfoPtr compInfo);
- static unsigned long FramesToSamples(unsigned long framesCount, CompressionInfoPtr compInfo);
- static void CompressThisMess(Byte *inputBuffer, Byte *outputBuffer, Byte *ulawTable, long samplesToConvert, short numChannels);
- static void GetCompressorInfo(CompressionInfoPtr cp);
- static void CompressULaw(SInt16 *inPtr, Byte *outPtr, Byte *ulawTable, long sampleCount, short numChannels, short whichChannel);
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // Component Dispatcher
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- #if TARGET_CPU_68K
- #define COMPONENT_C_DISPATCHER
- #define COMPONENT_DISPATCH_MAIN
- #endif
-
- #define CALLCOMPONENT_BASENAME() __uLawComp
- #define CALLCOMPONENT_GLOBALS() ULawCompGlobalsPtr storage
-
- #define SOUNDCOMPONENT_BASENAME() CALLCOMPONENT_BASENAME()
- #define SOUNDCOMPONENT_GLOBALS() CALLCOMPONENT_GLOBALS()
-
- #define COMPONENT_UPP_SELECT_ROOT() SoundComponent
- #define COMPONENT_DISPATCH_FILE "uLawCodecDispatch.h"
-
- #define GET_DELEGATE_COMPONENT() (storage->sourceComponent)
-
- #include "Components.k.h"
- #include "Sound.k.h"
- #include "ComponentDispatchHelper.c"
-
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // Component Routines
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static pascal ComponentResult __uLawCompOpen(ULawCompGlobalsPtr globals, ComponentInstance self)
- {
- OSErr result;
-
- globals = (ULawCompGlobalsPtr)NewPtrSysClear(sizeof(ULawCompGlobals));
- FailWithAction(globals == nil, result = MemError(), Failure);
-
- result = GetComponentResource((Component)self, k8BitTableResType, kSoundCompressorResID, &globals->ulawTableHandle);
- FailIf(result != noErr, NoResource);
-
- HLock(globals->ulawTableHandle);
- globals->ulawTable = (Byte *)StripAddress(*globals->ulawTableHandle);
-
- globals->self = self;
- globals->outputData.format = kOutputFormat; // output format
- globals->outputData.sampleSize = kOutputSampleSize; // output sample size
-
- globals->outputBufferSamples = kOutputSamples; // will be set to requested->sampleCount later
-
- // set our storage pointer to our globals
- SetComponentInstanceStorage(self, (Handle) globals);
- return (noErr);
-
- NoResource:
- DisposePtr((Ptr)globals);
- Failure:
- return (result);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static pascal ComponentResult __uLawCompClose(ULawCompGlobalsPtr globals, ComponentInstance self)
- {
- ComponentResult result;
-
- self; // suppress "unused variable" warning for all compilers
-
- if (globals != nil) // we have some globals
- {
- if (globals->sourceComponent)
- {
- result = CloseComponent(globals->sourceComponent); // torch source component
- FailMessage(result != noErr);
- }
- globals->outputData.sampleCount = 0; // nothing in our buffer now
-
- if (globals->ulawTableHandle != nil)
- DisposeHandle(globals->ulawTableHandle);
- DisposePtr((Ptr)globals); // torch them
- }
-
- return (noErr);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- pascal ComponentResult __uLawCompVersion(ULawCompGlobalsPtr globals)
- {
- globals; // suppress "unused variable" warning for all compilers
-
- return (kSoundCompressorVersion);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // Sound Component Methods
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static pascal ComponentResult __uLawCompSetSource(ULawCompGlobalsPtr globals, SoundSource sourceID, ComponentInstance source)
- {
- SoundComponentData sourceData;
- short i;
- Byte *bPtr;
-
- globals->sourceID = sourceID;
- globals->sourceComponent = source; // our food source
- globals->sourceDataPtr = nil; // nothing read from source yet
-
- bPtr = (Byte *)&sourceData; // zero out struct
- for (i = 0; i < sizeof(SoundComponentData); i++)
- bPtr = 0;
-
- sourceData.format = kInputFormat; // our source must give us this format
- sourceData.sampleSize = kInputSampleSize;
- sourceData.sampleCount = globals->outputBufferSamples;
-
- // make sure we can get the source we need
- return (noErr);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static pascal ComponentResult __uLawCompSetOutput(ULawCompGlobalsPtr globals, SoundComponentDataPtr requested, SoundComponentDataPtr *actual)
- {
- globals->outputBufferSamples = requested->sampleCount; // no. samples to output
- if (globals->outputBufferSamples > kOutputSamples) // too much for our buffer
- globals->outputBufferSamples = kOutputSamples;
-
- // must be one of the output formats we support
- if (requested->format != kOutputFormat)
- goto Failure;
-
- globals->outputData = *requested;
- return (noErr);
-
- Failure:
- // here's what we can do
- *actual = &globals->outputData;
- return (paramErr);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static pascal ComponentResult __uLawCompGetInfo(ULawCompGlobalsPtr globals, SoundSource sourceID, OSType selector, void *infoPtr)
- {
- ComponentResult result;
-
- result = noErr;
- switch (selector)
- {
- case siCompressionFactor:
- GetCompressorInfo(infoPtr);
- break;
-
- case siCompressionParams:
- result = GetCompressionParams(globals, infoPtr);
- break;
-
- case siOptionsDialog:
- *(short *)infoPtr = true;
- break;
-
- default:
- if (globals->sourceComponent == nil)
- result = siUnknownInfoType;
- else
- result = SoundComponentGetInfo(globals->sourceComponent, sourceID, selector, infoPtr);
- break;
- }
- return (result);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static pascal ComponentResult __uLawCompSetInfo(ULawCompGlobalsPtr globals, SoundSource sourceID, OSType selector, void *infoPtr)
- {
- ComponentResult result;
-
- result = noErr;
- switch (selector)
- {
- case siOptionsDialog:
- DisplayOptionsDialog(globals);
- break;
-
- case siCompressionParams:
- result = SetCompressionParams(globals, infoPtr);
- break;
-
- default:
- if (globals->sourceComponent == nil)
- result = siUnknownInfoType;
- else
- result = SoundComponentSetInfo(globals->sourceComponent, sourceID, selector, infoPtr);
- break;
- }
-
- return (result);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static pascal ComponentResult __uLawCompPlaySourceBuffer(ULawCompGlobalsPtr globals, SoundSource sourceID, SoundParamBlockPtr pb, long actions)
- {
- globals->sourceDataPtr = nil; // no source yet
- globals->outputData.sampleCount = 0; // our buffer is empty
-
- return (SoundComponentPlaySourceBuffer(globals->sourceComponent, sourceID, pb, actions));
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static pascal ComponentResult __uLawCompStopSource(ULawCompGlobalsPtr globals, short count, SoundSource *sources)
- {
- globals->sourceDataPtr = nil; // assume our source is gone
- globals->leftOverSamples = 0; // clear anything in leftover buffer
- return (SoundComponentStopSource(globals->sourceComponent, count, sources));
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static pascal ComponentResult __uLawCompGetSourceData(ULawCompGlobalsPtr globals, SoundComponentDataPtr *resultData)
- {
- SoundComponentDataPtr sourceDataPtr;
- long samplesToCopy;
- unsigned long bytesToCopy, framesToCopy, byteOffset;
- ComponentResult result = noErr;
-
- if (globals->sourceDataPtr == nil) // no source pointer so...
- {
- result = PrimeSource(globals); // get data from our source
- FailIf(result != noErr, Failure);
- }
-
- sourceDataPtr = globals->sourceDataPtr; // get pointer to source sound component
- if ((sourceDataPtr->format == globals->outputData.format) || // input and output are same
- (sourceDataPtr->buffer == nil)) // or no source buffer
- {
- globals->sourceDataPtr = nil; // get new source next time
- *resultData = sourceDataPtr; // pass source on down
- return (noErr); // get out
- }
-
- globals->outputData.buffer = globals->buffer; // initialize output buffer
- globals->outputData.sampleCount = 0;
-
- while ((sourceDataPtr->sampleCount < kULawBlockSamples) || // we don't have enough source for at least one block
- (globals->leftOverSamples)) // or we have samples in the leftover buffer
- {
- if (sourceDataPtr->sampleCount == 0) // used up all the source
- {
- result = SoundComponentGetSourceData(globals->sourceComponent, &globals->sourceDataPtr); // get more source
- FailIf(result != noErr, Failure);
- sourceDataPtr = globals->sourceDataPtr; // get pointer to source sound component
- if (sourceDataPtr->sampleCount == 0) // still no source samples - all done
- break;
- }
-
- samplesToCopy = kULawBlockSamples - globals->leftOverSamples; // compute samples needed to fill leftover buffer
- if (sourceDataPtr->sampleCount < samplesToCopy) // not enough source to fill it, so do what we can
- samplesToCopy = sourceDataPtr->sampleCount;
-
- // copy from source into leftover buffer
- bytesToCopy = SamplesToBytes(samplesToCopy, &globals->sourceCompInfo);
- byteOffset = SamplesToBytes(globals->leftOverSamples, &globals->sourceCompInfo);
- BlockMoveData(sourceDataPtr->buffer, globals->leftOverBuffer + byteOffset, bytesToCopy);
-
- sourceDataPtr->buffer += bytesToCopy; // samples removed from source
- sourceDataPtr->sampleCount -= samplesToCopy;
- globals->leftOverSamples += samplesToCopy; // keep track off samples in leftover buffer
-
- if (globals->leftOverSamples == kULawBlockSamples) // leftover buffer is full
- {
- CompressThisMess(globals->leftOverBuffer, globals->outputData.buffer, globals->ulawTable, kULawBlockSamples, sourceDataPtr->numChannels);
-
- globals->outputData.buffer += SamplesToBytes(kULawBlockSamples, &globals->destCompInfo);
- globals->outputData.sampleCount += kULawBlockSamples;
- globals->leftOverSamples = 0;
-
- if (globals->outputData.sampleCount == kOutputSamples) // output buffer is full
- break; // stop converting
- }
- }
-
- samplesToCopy = kOutputSamples - globals->outputData.sampleCount; // find amount available in output buffer
- if (samplesToCopy > sourceDataPtr->sampleCount) // don't copy more than we have
- samplesToCopy = sourceDataPtr->sampleCount;
-
- framesToCopy = SamplesToFrames(samplesToCopy, &globals->destCompInfo);
-
- if (framesToCopy) // source has some data for us
- {
- samplesToCopy = FramesToSamples(framesToCopy, &globals->destCompInfo);
-
- CompressThisMess(sourceDataPtr->buffer, globals->outputData.buffer, globals->ulawTable, samplesToCopy, sourceDataPtr->numChannels);
-
- sourceDataPtr->buffer += SamplesToBytes(samplesToCopy, &globals->sourceCompInfo); // update input buffer
- sourceDataPtr->sampleCount -= samplesToCopy;
-
- globals->outputData.buffer += SamplesToBytes(samplesToCopy, &globals->destCompInfo);
- globals->outputData.sampleCount += samplesToCopy;
- }
-
- globals->outputData.buffer = globals->buffer; // reset to beginning of buffer
- *resultData = &globals->outputData; // tell them what we made
- return (noErr);
-
- Failure:
- return (result);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // sub routines _
- // _|_
- // o _____| |_____
- // o o +______________/
- //
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static OSErr DisplayOptionsDialog(ULawCompGlobalsPtr globals)
- {
- DialogPtr dialog;
- short resFile;
- short currentResFile;
- short itemHit;
- OSErr result;
-
- result = noErr;
- currentResFile = CurResFile();
- resFile = OpenComponentResFile((Component)globals->self);
- FailWithAction(resFile == kResFileNotOpened, result = ResError(), Exit);
-
- dialog = GetNewDialog(kSoundCompressorResID, nil, (WindowPtr)-1);
- FailWithAction(dialog == nil, result = resNotFound, NoDialog);
-
- MacSetPort(dialog);
- SetButtonState(dialog, kOptionCheckBox, true);
- SetDialogDefaultItem(dialog, kStdOkItemIndex);
- SetDialogCancelItem(dialog, kStdCancelItemIndex);
- MacShowWindow(dialog);
-
- do
- {
- ModalDialog(nil, &itemHit);
- switch (itemHit)
- {
- case kOptionCheckBox:
- if (GetButtonState(dialog, kOptionCheckBox))
- SetButtonState(dialog, kOptionCheckBox, false);
- else
- SetButtonState(dialog, kOptionCheckBox, true);
- break;
-
- case kStdOkItemIndex:
- GetButtonState(dialog, kOptionCheckBox);
- // accept changes according to values set in dialog
- break;
- }
- } while ( (itemHit != kStdOkItemIndex) && (itemHit != kStdCancelItemIndex) );
-
- DisposeDialog(dialog);
-
- NoDialog:
- CloseResFile(resFile);
- Exit:
- UseResFile(currentResFile);
- return (result);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static void SetButtonState(DialogPtr dialog, short item, Boolean state)
- {
- short iType;
- Handle iHandle;
- Rect iRect;
-
- GetDialogItem(dialog, item, &iType, &iHandle, &iRect);
- if (iHandle != nil)
- SetControlValue((ControlHandle) iHandle, (state) ? kControlRadioButtonCheckedValue : kControlRadioButtonUncheckedValue);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static short GetButtonState(DialogPtr dialog, short item)
- {
- short iType;
- Handle iHandle;
- Rect iRect;
-
- GetDialogItem(dialog, item, &iType, &iHandle, &iRect);
- return (GetControlValue((ControlHandle) iHandle));
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static OSErr GetCompressionParams(ULawCompGlobalsPtr globals, AudioCompressionAtomHandle *params)
- {
- AudioCompressionAtomHandle atom;
- AudioCompressionAtomPtr atomPtr;
- OSErr result;
-
- globals; // suppress "unused variable" warning for all compilers
-
- result = noErr;
- atom = (AudioCompressionAtomHandle)NewHandle(sizeof(AudioCompressionAtom));
- FailWithAction(atom == nil, result = MemError(), Exit);
-
- atomPtr = *atom;
- atomPtr->formatData.size = EndianU32_NtoB(sizeof(AudioFormatAtom));
- atomPtr->formatData.atomType = EndianU32_NtoB(kAudioFormatAtomType);
- atomPtr->formatData.format = EndianU32_NtoB(kOutputFormat);
-
- atomPtr->endianData.size = EndianU32_NtoB(sizeof(AudioEndianAtom));
- atomPtr->endianData.atomType = EndianU32_NtoB(kAudioEndianAtomType);
- atomPtr->endianData.littleEndian = EndianU16_NtoB(false); // µlaw is not little endian
-
- atomPtr->terminatorData.size = EndianU32_NtoB(sizeof(AudioTerminatorAtom));
- atomPtr->terminatorData.atomType = EndianU32_NtoB(kAudioTerminatorAtomType);
-
- *params = atom;
-
- Exit:
- return (result);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static OSErr SetCompressionParams(ULawCompGlobalsPtr globals, UserDataAtom *atom)
- {
- OSErr result;
- short littleEndian;
- Boolean moreAtoms;
-
- globals; // suppress "unused variable" warning for all compilers
-
- result = noErr;
- moreAtoms = true;
- littleEndian = false;
- do
- {
- long atomSize = EndianS32_BtoN(atom->size);
- FailWithAction(atomSize < 8, result = invalidAtomErr, Exit);
- switch (EndianU32_BtoN(atom->atomType))
- {
- case kAudioFormatAtomType:
- FailWithAction(((AudioFormatAtom *)atom)->format != EndianU32_NtoB(kOutputFormat), result = badFormat, Exit);
- break;
-
- case kAudioEndianAtomType:
- littleEndian = EndianU16_BtoN(((AudioEndianAtom *)atom)->littleEndian);
- break;
-
- case kAudioTerminatorAtomType:
- moreAtoms = false;
- break;
-
- default: // unknown atom type
- break;
- }
- atom = (UserDataAtom *)((long)atom + atomSize);
- } while (moreAtoms);
- if (littleEndian)
- result = paramErr; // we do not do little endian
-
- Exit:
- return (result);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static ComponentResult PrimeSource(ULawCompGlobalsPtr globals)
- {
- ComponentResult result = noErr;
- SoundComponentDataPtr sourceDataPtr;
-
- result = SoundComponentGetSourceData(globals->sourceComponent, &globals->sourceDataPtr);
- FailIf(result != noErr, Failure);
- FailWithAction(globals->sourceDataPtr == nil, result = paramErr, Failure);
-
- sourceDataPtr = globals->sourceDataPtr;
- globals->outputData.flags = sourceDataPtr->flags; // copy flags unchanged
- globals->outputData.sampleRate = sourceDataPtr->sampleRate; // copy sample rate unchanged
- globals->outputData.numChannels = sourceDataPtr->numChannels; // copy numchannels unchanged
-
- globals->sourceCompInfo.recordSize = sizeof(CompressionInfo); // get source compression info
- result = GetCompressionInfo(fixedCompression, sourceDataPtr->format,
- sourceDataPtr->numChannels, sourceDataPtr->sampleSize,
- &globals->sourceCompInfo);
- FailIf(result != noErr, Failure);
-
- globals->destCompInfo.recordSize = sizeof(CompressionInfo);
- GetCompressorInfo(&globals->destCompInfo); // get dest compression info
- globals->destCompInfo.bytesPerFrame = globals->destCompInfo.bytesPerPacket * sourceDataPtr->numChannels;
-
- Failure:
- return (result);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static unsigned long SamplesToBytes(unsigned long sampleCount, CompressionInfoPtr compInfo)
- {
- return ((sampleCount / compInfo->samplesPerPacket) * compInfo->bytesPerFrame);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static unsigned long BytesToSamples(unsigned long byteCount, CompressionInfoPtr compInfo)
- {
- return ((byteCount / compInfo->bytesPerFrame) * compInfo->samplesPerPacket);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static unsigned long SamplesToFrames(unsigned long sampleCount, CompressionInfoPtr compInfo)
- {
- return (sampleCount / compInfo->samplesPerPacket);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static unsigned long FramesToSamples(unsigned long frameCount, CompressionInfoPtr compInfo)
- {
- return (frameCount * compInfo->samplesPerPacket);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static void CompressThisMess(Byte *inputBuffer, Byte *outputBuffer, Byte *ulawTable, long samplesToConvert, short numChannels)
- {
- if (numChannels == 1)
- {
- CompressULaw((SInt16 *) inputBuffer, outputBuffer, ulawTable, samplesToConvert, 1, 1);
- }
- else
- {
- CompressULaw((SInt16 *) inputBuffer, outputBuffer, ulawTable, samplesToConvert, 2, 1);
- CompressULaw((SInt16 *) inputBuffer, outputBuffer, ulawTable, samplesToConvert, 2, 2);
- }
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static void GetCompressorInfo(CompressionInfoPtr cp)
- {
- if (cp->recordSize > sizeof(CompressionInfo)) // limit amount we return
- cp->recordSize = sizeof(CompressionInfo);
-
- cp->compressionID = fixedCompression;
- cp->format = kOutputFormat;
- cp->samplesPerPacket = kULawBlockSamples;
- cp->bytesPerPacket = kULawBlockBytes;
- cp->bytesPerSample = kULawBytesPerSample;
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- static void CompressULaw(SInt16 *inPtr, Byte *outPtr, Byte *ulawTable, long sampleCount,
- short numChannels, short whichChannel)
- {
- long sampnum;
- int sample, sign, exponent, mantissa;
- unsigned char ulawbyte;
-
- whichChannel -= 1;
- inPtr += whichChannel; /* skip to first sample */
- outPtr += whichChannel;
-
- for (sampnum = 0; sampnum < sampleCount; sampnum++)
- {
- sample = *inPtr;
- inPtr += numChannels; /* skip to next sample */
-
- /* Get the sample into sign-magnitude. */
- sign = (sample >> 8) & 0x80; /* set aside the sign */
- if (sign != 0)
- sample = -sample; /* get magnitude */
- if (sample > CLIP)
- sample = CLIP; /* clip the magnitude */
-
- /* Convert from 16 bit linear to ulaw. */
- sample = sample + BIAS;
- exponent = ulawTable[(sample >> 7) & 0xFF];
- mantissa = (sample >> (exponent + 3)) & 0x0F;
- ulawbyte = ~(sign | (exponent << 4) | mantissa);
- #ifdef ZEROTRAP
- if (ulawbyte == 0)
- ulawbyte = 0x02; /* optional CCITT trap */
- #endif
- *outPtr = ulawbyte; /* output compressed sample */
- outPtr += numChannels;
- }
- }
-